Skip to content

feat: expand Data Fabric entities service [DS-8360]#1616

Open
avichalsri24 wants to merge 1 commit into
mainfrom
task/sync_entities_sdk
Open

feat: expand Data Fabric entities service [DS-8360]#1616
avichalsri24 wants to merge 1 commit into
mainfrom
task/sync_entities_sdk

Conversation

@avichalsri24
Copy link
Copy Markdown

@avichalsri24 avichalsri24 commented May 7, 2026

Summary

Adds the missing Data Fabric methods on EntitiesService and exposes the full backend parameter set on existing batch methods. Internally splits the service for clearer separation between schema- and data-side operations while keeping the public sdk.entities.* surface unchanged.

Jira: https://uipath.atlassian.net/browse/DS-8360

Internal structure

EntitiesService is now a thin facade that delegates to two internal sub-services:

Sub-service (internal) Backend target Responsibilities
EntitySchemaService (in _entity_schema_service.py, not exported) datafabric_/api/Entity entity / choiceset retrieval + create / delete / metadata update
EntityDataService (in _entity_data_service.py, not exported) datafabric_/api/EntityService/... + Attachment + v1/query/execute record CRUD (single + batch), structured query, FQS SQL query, attachments, bulk import, choiceset values

Sub-services are deliberately not exported via __init__.pysdk.entities.* remains the only sanctioned entry point. EntityDataService.query is the new structured-query method (named query so it can't be confused with the existing FQS query_entity_records, which is fully intact).

New methods (sync + async on the facade)

  • Single-record ops: insert_record, get_record, update_record, delete_record — fire trigger events on each mutation.
  • query — structured query with filter_group, sort_options, selected_fields, expansions, expansion_level, aggregates, group_by, joins, binnings, start, limit. Routes to V2 endpoint when binnings is supplied.
  • Attachments: upload_attachment (bytes or path), download_attachment, delete_attachment.
  • Schema: create_entity (with full SQL-type mapping and per-type constraint defaults), delete_entity, update_entity_metadata.
  • import_records for CSV bulk upload.

Existing methods extended

  • insert_records / update_records / delete_records accept expansion_level and fail_on_first.
  • list_records accepts OData filter / orderby / select / expand / expansion_level and returns EntityRecordsListResponse (a list subclass with total_count / has_next_page / next_cursor).

Bug fixes

  • Batch operations recover per-record failures from HTTP 400 responses that carry successRecords / failureRecords lists; other non-2xx statuses propagate.
  • Record input is normalized — accepts dicts, Pydantic models, EntityRecord, or any object with __dict__.

Client-side validation

create_entity validates entity / field names client-side using the UI's create-form rules: ^[a-zA-Z][a-zA-Z0-9]*$ (no underscores), entity 1–30 chars, field 3–100 chars, plus reserved-name and per-field constraint range checks. Anything accepted by the SDK round-trips cleanly through the Data Service UI.

Backward compatibility

Public method signatures only gained optional kwargs. EntityRecord.id stays required. list_records return type subclasses list, so iteration / indexing / len() / isinstance(records, list) continue to work. Existing docstrings are preserved verbatim from main; only ticket-mandated additions (new param entries, new Examples, new return types) appear in their docs.

Test plan

  • pytest packages/uipath-platform/tests/services/test_entities_service.py — 112 pass
  • pytest packages/uipath-platform/tests/ — 1158 pass
  • pytest packages/uipath/tests/ — 1840 pass
  • ruff check, ruff format --check, mypy src tests, custom lint_httpx_client.py — clean across both packages
  • Live smoke against a Data Fabric tenant before release tag

🤖 Generated with Claude Code

@github-actions github-actions Bot added test:uipath-langchain Triggers tests in the uipath-langchain-python repository test:uipath-integrations labels May 7, 2026
@avichalsri24 avichalsri24 changed the title feat(platform): expand Data Fabric entities service [DS-8360] feat: expand Data Fabric entities service [DS-8360] May 7, 2026
@UIPath-Harshit UIPath-Harshit requested a review from Copilot May 7, 2026 12:44
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands the Data Fabric EntitiesService surface area by adding missing Data Fabric entity operations (single-record CRUD, structured query, attachments, schema management, bulk import) and by exposing more backend parameters/metadata on existing batch and list endpoints.

Changes:

  • Added new Data Fabric APIs to EntitiesService: single-record CRUD, structured query (V1/V2 routing), attachments, entity schema create/update/delete, and CSV bulk import (sync + async).
  • Extended existing record list/batch operations to support additional backend parameters and richer pagination metadata (EntityRecordsListResponse), plus improved batch error recovery for per-record failures on HTTP 400.
  • Added/updated entity/query/schema models and comprehensive tests for the new behaviors.

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/uipath/uv.lock Bumps editable uipath-platform version reference.
packages/uipath-platform/uv.lock Bumps uipath-platform version to 0.1.47.
packages/uipath-platform/pyproject.toml Version bump to 0.1.47.
packages/uipath-platform/src/uipath/platform/entities/entities.py Adds new response/query/schema models (batch failure shape, list response w/ metadata, structured query types).
packages/uipath-platform/src/uipath/platform/entities/_entities_service.py Implements the new/extended EntitiesService methods and request/response helpers.
packages/uipath-platform/src/uipath/platform/entities/init.py Exposes the newly added entities/query/schema symbols via package exports.
packages/uipath-platform/tests/services/test_entities_service.py Adds test coverage for new methods, query routing, attachments, schema creation defaults, and validation/error recovery.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2494 to +2498
if isinstance(metadata, EntityMetadataUpdateOptions):
body = metadata.model_dump(by_alias=True, exclude_none=True)
else:
body = dict(metadata)
return RequestSpec(
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dict inputs now route through EntityMetadataUpdateOptions.model_validate(...) then model_dump(by_alias=True, exclude_none=True), so display_name/is_rbac_enabled get serialized as displayName/isRbacEnabled on the wire. New test test_update_entity_metadata_normalizes_snake_case_dict_keys locks this in.

"fields": [self._build_schema_field_payload(f) for f in fields],
"folderId": opts.folder_key or DATA_FABRIC_TENANT_FOLDER_ID,
"isRbacEnabled": bool(opts.is_rbac_enabled or False),
"isInsightsEnabled": bool(opts.is_analytics_enabled or False),
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is_analytics_enabled → isInsightsEnabled — added a one-line comment at the payload site explaining the legacy wire-name divergence.

Comment on lines +546 to +548
def __getitem__(self, index: int) -> EntityRecord:
"""Index records by position (delegates to ``self.items``)."""
return self.items[index]
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added @overload for int and slice on EntityQueryRecordsResponse, so slicing returns List[EntityRecord] and indexing returns EntityRecord with proper type narrowing.

Comment on lines +553 to 556
) -> EntityRecordsListResponse:
"""Asynchronously list records from an entity with optional pagination and schema validation.

The schema parameter enables type-safe access to entity records by validating the
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring now mirrors the sync version: Args list includes expansion_level, filter, orderby, select, expand; Returns describes EntityRecordsListResponse with pagination metadata; Examples include an OData filter/orderby/select/expand sample.

FileContent = Union[bytes, bytearray, memoryview]
"""Acceptable raw bytes types for attachment/CSV uploads."""

_NAME_RE = re.compile(r"^[a-zA-Z]\w*$")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this consistent with backend?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified against the UI's create-form validators. Tightened _NAME_RE to ^[a-zA-Z][a-zA-Z0-9]*$ (no underscores) and split lengths by context: entity 1–30, field 3–100. Anything accepted by the SDK can now round-trip through the UI.

)

return self.validate_entity_batch(response, schema)
async def _do() -> Response:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better name here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to _send_batch

),
)

def _query_records_spec(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!!! You are swapping out the query_records_spec which is catering to FQS query endpoint from DataService. This breaks multiple APIs for agents. Right strategy to avoid this is:

  1. Isolate the changes for schema into EntitySchemaService
  2. Isolate the changes for data into EntityDataService.
  3. EntityService is a facade that doesnt change the external contract.
  4. Carefully understand the APIs for DS and FQS and then make these changes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, this is a new method for odata query and not impacting sql endpoint consumed by agents (query_entity_records_spec vs query_records_spec).

Regarding refactor, updated the code, split into EntitySchemaService (entity/choiceset CRUD) and EntityDataService (records, attachments, queries — both FQS query_entity_records and DS query). EntitiesService is now a thin facade that preserves the existing flat sdk.entities.* contract via explicit delegation. No external API change. The new DS structured-query method is named query (not query_records) so it can't be confused with the existing FQS query_entity_records, which is fully intact. Sub-services are kept internal (not exported in init.py).

@github-actions
Copy link
Copy Markdown

🚨 Heads up: uipath-langchain cross-tests are FAILING 🚨

Your changes may break the uipath-langchain-python integration.

⚠️ These checks are NOT enforced by branch protection rules. Please review the failures before merging.

🔍 Inspect the failed run →

Adds the missing Data Fabric methods on EntitiesService and exposes the
full backend parameter set on existing batch methods.

Internally splits the service into a facade pattern for clearer
separation between schema- and data-side operations while keeping the
public sdk.entities.* surface unchanged:

  - EntitySchemaService (internal): entity / choiceset CRUD against
    datafabric_/api/Entity.
  - EntityDataService (internal): record CRUD (single + batch), structured
    query, federated SQL query, attachments, bulk import, choiceset
    values, against datafabric_/api/EntityService/... +
    datafabric_/api/Attachment + datafabric_/api/v1/query/execute.
  - EntitiesService (public): thin facade that delegates to the two
    sub-services and owns cross-cutting concerns (agent entity-set
    resolution).

New methods (sync + async on the facade):
  - Single-record ops: insert_record, get_record, update_record,
    delete_record — fire trigger events on each mutation.
  - query — structured query with filter_group, sort_options,
    selected_fields, expansions, expansion_level, aggregates, group_by,
    joins, binnings, start, limit. Routes to V2 endpoint when binnings
    is supplied.
  - Attachments: upload_attachment (bytes or path), download_attachment,
    delete_attachment.
  - Schema: create_entity (with SQL-type mapping and per-type constraint
    defaults), delete_entity, update_entity_metadata.
  - import_records for CSV bulk upload.

Existing methods extended (ticket §B):
  - insert_records / update_records / delete_records accept
    expansion_level and fail_on_first.
  - list_records accepts OData filter / orderby / select / expand /
    expansion_level and returns EntityRecordsListResponse (a list
    subclass with total_count / has_next_page / next_cursor).

Bug fixes (ticket §C):
  - Batch operations recover per-record failures from HTTP 400 responses
    that carry successRecords / failureRecords lists; other non-2xx
    statuses propagate.
  - Record input is normalized — accepts dicts, Pydantic models,
    EntityRecord, or any object with __dict__.

Client-side validation in create_entity uses the UI's create-form rules:
^[a-zA-Z][a-zA-Z0-9]*$ (no underscores), entity 1-30 chars, field 3-100
chars, plus reserved-name and per-field constraint range checks. Anything
accepted by the SDK round-trips cleanly through the Data Service UI.

Backward compatibility: public method signatures only gained optional
kwargs. EntityRecord.id stays required. list_records return type
subclasses list, so iteration / indexing / len() / isinstance(records,
list) continue to work. Existing method docstrings preserved verbatim
from main; only ticket-mandated additions appear in their docs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@avichalsri24 avichalsri24 force-pushed the task/sync_entities_sdk branch from ff1d809 to bcabb27 Compare May 11, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:uipath-integrations test:uipath-langchain Triggers tests in the uipath-langchain-python repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants